package ferp.core.game;


import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * User: olegs
 * Date: 01/03/12 22:55
 */
public class Settings
{
  public static class InitializationException extends Exception
  {
    public InitializationException() {}

    public InitializationException(String detailMessage) {super(detailMessage);}

    public InitializationException(String detailMessage, Throwable throwable) {super(detailMessage, throwable);}

    public InitializationException(Throwable throwable) {}
  }

  public static final class Delays
  {
    public static final int DEFAULT = 0;
    public static final int AFTER_BID = 1 * 1000;
    public static final int AFTER_CONTRACT = 1 * 1000;
    public static final int AFTER_DROP = 500;
    public static final int AFTER_CARD_PLAYED = 500;
    public static final int AFTER_ROUND_END = 1 * 1000;
  }

  public final static int INITIAL_POOL_SIZE = 20;
  // Rostov passing trick cost
  public final static int ROSTOV_PASSING_TRICK_COST = 5;

  // number of passing interruption options
  public static final int PASSING_INTERRUPTION_OPTIONS_COUNT = 4;

  // default animation time in milliseconds
  public static final long ANIMATION_TIME = 250;

  // local deck name
  public static final String DECK_STANDARD = "standard";

  // game flavors
  public static enum GameFlavor{SOCHI, LENINGRAD, ROSTOV}
  // game levels
  public static enum Level {L0, L1, L2, L3}
  // whist types
  public static enum WhistType {GENTLEMAN, GREEDY}
  // whist on 6 spades types
  public static enum WhistOn6Spades {MANDATORY, ARBITRARY}
  // passing type
  public static enum PassingType {SLIDING, CLASSIC}
  // passing progressions
  public static enum PassingProgression {PP_1111, PP_123123, PP_1233, PP_1244, PP_1234, PP_1248}
  // passing trick cost
  public static enum PassingTrickCost {PTC_1, PTC_2}
  // passing exit types
  public static enum PassingExit {PE_6666, PE_6777, PE_6788, PE_678678}
  // misere modes
  public static enum MisereMode {DEFAULT, HUMAN, ANDROID}
  // suit orders
  public static enum SuitOrder {COLOR, COLOR_WITHOUT_REORDERING, RANK}
  // rank orders
  public static enum RankOrder {ASCENDING, DESCENDING}
  // screen orientations
  public static enum Orientation {PORTRAIT, LANDSCAPE}
  // confirmations
  public static enum Confirmation {ALWAYS, INTELLIGENT, NEVER}
  // tricking 10 modes
  public static enum Tricking10 {WHISTED, CHECKED}
  // animation time in milliseconds
  public long animationTime = ANIMATION_TIME;
  // cloud save options
  public static enum CloudSave {EVERY_SET, EVERY_GAME, NONE}

  public static enum Locale
  {
    ENGLISH, RUSSIAN;

    // get locale country code
    public String code() {return codes[ordinal()];}
    // get locale by country code
    public static Locale locale(String code)
    {
      Locale l = locales.get(code);
      return l == null ? ENGLISH : l;
    }

    // country codes
    private static final String[] codes = {"en", "ru"};
    // country code to locale map
    private static final Map<String, Locale> locales = new HashMap<String, Locale>();

    static
    {
      locales.put("en", ENGLISH);
      locales.put("ru", RUSSIAN);
    }
  }

  public static class Folders
  {
    public static final String FERP = "ferp";

    // profile files directory
    public static File profiles;
    // log directory
    public static File logs;
  }

  public static void initialize(File home) throws InitializationException
  {
    // initialize folders
    Folders.profiles = initialize(home, "profiles");
    Folders.logs = initialize(home, "logs");
  }

  public boolean isLandscape() {return orientation == Settings.Orientation.LANDSCAPE;}

  public boolean isRostov() {return gameFlavor == GameFlavor.ROSTOV;}

  public boolean isPassingInterruptedByMisere(int tricks)
  {
    return tricks == 0 && passingInterruptions[SUCCESSFUL_MISERE] || tricks > 0 && passingInterruptions.length > 3 && passingInterruptions[FAILED_MISERE];
  }

  public boolean isPassingInterruptedByNonWhistedGame() {return passingInterruptions[Settings.NON_WHISTED_GAME];}
  public boolean isPassingInterruptedByFailedGame() {return passingInterruptions.length > 2 && passingInterruptions[Settings.FAILED_GAME];}

  // player levels level
  public Level[] levels = {Level.L0, Level.L0};
  // pool size
  public int poolSize = INITIAL_POOL_SIZE;
  // calculator
  public GameFlavor gameFlavor = GameFlavor.SOCHI;
  // passing type
  public PassingType passingType = PassingType.SLIDING;
  // passing progression
  public PassingProgression passingProgression = PassingProgression.PP_123123;
  // passing trick cost
  public PassingTrickCost passingTrickCost = PassingTrickCost.PTC_1;
  // passing exit
  public PassingExit passingExit = PassingExit.PE_6777;
  // misere mode
  public MisereMode misereMode = MisereMode.DEFAULT;
  // whist type
  public WhistType whistType = WhistType.GREEDY;
  // whist on 6 spades type
  public WhistOn6Spades whistOn6Spades = WhistOn6Spades.MANDATORY;
  // suit order
  public SuitOrder suitOrder = SuitOrder.COLOR;
  // rank order in suit
  public RankOrder rankOrder = RankOrder.ASCENDING;
  // spacing between suits
  public boolean suitSpacing = false;
  // locale
  public Locale locale = Locale.ENGLISH;
  // orientation
  public Orientation orientation = Orientation.PORTRAIT;
  // cloud save
  public CloudSave cloudSave = CloudSave.NONE;

  public static final class Confirmations
  {
    public interface Changer
    {
      void change(Confirmations confirmations, Confirmation value);
    }

    // confirm bid
    public Confirmation bid = Confirmation.ALWAYS;
    // confirm contract
    public Confirmation contract = Confirmation.ALWAYS;
  }

  public Confirmations confirmations = new Confirmations();

  // round end tapping preferences
  public boolean roundEndTapWhenNotPlaying = true;
  public boolean roundEndTapWhenLastMoverAndroid = true;
  public boolean roundEndTapWhenLastMoverHuman = false;
  // automate obvious moves for human
  public boolean automateObviousMoves = false;
  // passing interruptions
  public boolean[] passingInterruptions = new boolean[PASSING_INTERRUPTION_OPTIONS_COUNT];
  // skip game on pass
  public boolean skipGameOnPass = false;
  // tricking 10 mode
  public Tricking10 tricking10 = Tricking10.CHECKED;
  // deck's name
  public String deck = DECK_STANDARD;

  // passing interruptions indexes
  private final static int SUCCESSFUL_MISERE = 0;
  private final static int NON_WHISTED_GAME  = 1;
  private final static int FAILED_GAME       = 2;
  private final static int FAILED_MISERE     = 3;

  private static File initialize(File parent, String name) throws InitializationException
  {
    // check parent folder's permissions
/*
    if (!parent.canRead())
      throw new InitializationException("Folder '" + parent + "' does not have read permissions");

    if (!parent.canWrite())
      throw new InitializationException("Folder '" + parent + "' does not have write permissions");
*/

    // prepare sub folder's File object
    File folder = new File(parent, name);

    // try to create a sub folder if does not exist
    if (!folder.exists() && !folder.mkdir())
      throw new InitializationException("Unable to create folder '" + name + "' under '" + parent + "'");

    // check created sub folder's permissions
/*
    if (!folder.canRead())
      throw new InitializationException("Folder '" + folder + "' does not have read permissions");

    if (!folder.canWrite())
      throw new InitializationException("Folder '" + folder + "' does not have write permissions");
*/

    return folder;
  }
}
